import {LLM} from 'langchain/llms/base'

export class Cheese extends LLM {
    constructor(fields) {
        super(fields ?? {});
        Object.defineProperty(this, "streaming", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "baseUrl", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        this.baseUrl = fields?.baseUrl ?? 'http://43.134.44.205:30625/context_batch_return';
        this.streaming = fields?.streaming ?? false;
    }
    _llmType() {
        return "cheese_chat";
    }
    async _call(prompt, options, runManager) {
        const baseUrl = this.baseUrl
        const headers = {
            "Content-Type": "application/json",
        };
        const data = {
            text: prompt,
            message: [],
            is_bots: []
        };
        return await this.caller.callWithOptions({signal: options.signal}, async () => {
                const response = await fetch(baseUrl, {
                    method: "POST",
                    headers,
                    body: JSON.stringify(data),
                    signal: options.signal,
                });
                const reader = response.body.getReader();
                const decoder = new TextDecoder('utf-8');
                let last_index = 0;
                let buffer = '';
                let res = '';
                while (true) {
                    try {
                        const {done, value} = await reader.read()
                        if (done) {
                            break;
                        }
                        buffer += decoder.decode(value);
                        const delimiterIndex = buffer.indexOf('\0');
                        if (delimiterIndex !== -1) {
                            let decodedText = buffer.substring(0, delimiterIndex);
                            buffer = '';
                            try {
                                decodedText = JSON.parse(decodedText);
                                if (decodedText.status === 'Success') {
                                    res = decodedText.text
                                    if(this.streaming){
                                        void runManager?.handleLLMNewToken(decodedText.text.slice(last_index))
                                    }
                                    last_index = decodedText.text.length;
                                } else if (decodedText.status === 'Fail') {
                                    break;
                                }
                            } catch (e) {
                                break
                            }
                        }
                    } catch (e) {
                        break
                    }
                }
                return res
            })
    }
}
